﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

namespace AppRPG
{
    public class Editor
    {
        private List<PhysObject.PhysObject> _accessPhysicalObjects;
        public int BeginShowAccessPhysicalObjects;

        private List<PhysObject.PhysObject> _makedPhysicalObjects;

        public PhysObject.PhysObject CurrentPhysicalObject;

        public PhysObject.PhysObject ChoosePhysicalObject;
        public PhysObject.PhysObject MovingPhysicalObject;
        public PhysObject.PhysObject LastMovingGameObject;

        public Point OldPositionMouse;

        private Point _oldPositionMovingGameObject;

        private Point _beginPosition;
        private int delta;

        public bool IsSave;

        private Frame _frame;

        public Point Center;

        public List<TextBox> TextBoxes;
        public List<ToolStripMenuItem> ToolStripMenuItems;
        public List<Label> Labels;


        public bool IsOn;

        public bool IsClick;

        public bool ShowAllObjects;

        public Editor()
        {
            IsSave = true;
            IsOn = true;
            _accessPhysicalObjects = new List<PhysObject.PhysObject>();
            _makedPhysicalObjects = new List<PhysObject.PhysObject>();
            OldPositionMouse = Point.Empty;
            delta = 0;
            _beginPosition = new Point(0, 50);
            _accessPhysicalObjects.AddRange(FileMapManager.LoadConfiguration());

            foreach (var accessPhysicalObject in _accessPhysicalObjects)
            {
                accessPhysicalObject.SetDimension(new Size(100, 70));
                accessPhysicalObject.SetPosition(new Point(200, _beginPosition.Y + 30 + delta));
                delta += 100;
            }
            delta = 100;
            int size = _accessPhysicalObjects.Count * delta;
            Center = Point.Empty;
            _frame = new Frame(new Size(300, size), _beginPosition, delta);
        }

        public void OpenFile(string path)
        {
            _makedPhysicalObjects.Clear();
            LastMovingGameObject = null;
            _makedPhysicalObjects.AddRange(FileMapManager.LoadPhysicalObjects(path));
        }

        public void Close()
        {
        }

        public void SaveFile()
        {
            FileMapManager.SavePhysicalObjectsToFile(_makedPhysicalObjects);
            IsSave = true;
        }

        public void SaveAs(string path)
        {
            FileMapManager.SavePhysicalObjectsToFile(_makedPhysicalObjects, path);
            IsSave = true;
        }

        public void ShowScrollAccessGameObjects(Graphics device, Button button)
        {
            int positionY = _beginPosition.Y;

            _frame.PaintFrame(device);
            for (int i = 0; i < _accessPhysicalObjects.Count; i++)
            {
                if (CurrentPhysicalObject == _accessPhysicalObjects[i])
                {
                    ShowGameObject(device, _accessPhysicalObjects[i], new Point(_beginPosition.X, positionY));


                    Pen pen = new Pen(Color.LightGray, 5);
                    device.DrawRectangle(pen, _beginPosition.X, positionY, 300, delta);
                    ShowChoose(button, new Point(_beginPosition.X, positionY + delta / 2));
                }
                else
                {
                    ShowGameObject(device, _accessPhysicalObjects[i], new Point(_beginPosition.X, positionY));
                }
                positionY += delta;
            }
        }

        public void ShowGameObject(Graphics device, PhysObject.PhysObject physicalObject, Point position)
        {
            Font font = new Font("Arial", 15);
            device.DrawString(physicalObject.ToString(), font, Brushes.Black, position);
            physicalObject.Draw(device);
        }

        public void ShowMakedGameObjects(Graphics device)
        {
            foreach (var makedPhysicalObject in _makedPhysicalObjects)
            {
                //makedPhysicalObject.Draw(device);
                //if (makedPhysicalObject != MovingPhysicalObject)
                Point oldPositon = makedPhysicalObject.GetPosition();
                makedPhysicalObject.SetPosition(new Point(Center.X + oldPositon.X,
                                                           Center.Y + oldPositon.Y));
                makedPhysicalObject.Draw(device);
                makedPhysicalObject.SetPosition(oldPositon);
            }
        }

        public void ShowCurrentGameObject(Graphics device)
        {
            //if (CurrentPhysicalObject != null)
            //    device.draw
        }

        public void MakeGameObject()
        {
            _makedPhysicalObjects.Add(CurrentPhysicalObject);
        }

        public void ShowChoose(Button button, Point location)
        {
            if (CurrentPhysicalObject != null)
                button.Location = location;
        }

        public void AcceptChoose()
        {
            ChoosePhysicalObject = CurrentPhysicalObject;
            LastMovingGameObject = MovingPhysicalObject = CreateCopy(ChoosePhysicalObject);
        }

        private PhysObject.PhysObject CreateCopy(PhysObject.PhysObject physObject)
        {
            Type type = physObject.GetType();
            ConstructorInfo constructorInfo = type.GetConstructor(new[] { typeof(string), typeof(Point), typeof(Size), typeof(Image) });
            return (PhysObject.PhysObject)constructorInfo.Invoke(new object[] { physObject.GetObjectName(), physObject.GetPosition(), physObject.GetDimension(), physObject.GetTexture() });
        }

        public void ShowMovingGameObject(Graphics device)
        {
            if (MovingPhysicalObject != null && !_makedPhysicalObjects.Contains(MovingPhysicalObject))
                MovingPhysicalObject.Draw(device);
        }

        public void MoveChooseGameObject(Point locationMouse)
        {
            if (MovingPhysicalObject != null && ChoosePhysicalObject == null)
            {
                _oldPositionMovingGameObject = MovingPhysicalObject.GetPosition();
                MovingPhysicalObject.SetPosition(new Point(MovingPhysicalObject.GetPosition().X - (OldPositionMouse.X - locationMouse.X),
                        MovingPhysicalObject.GetPosition().Y - (OldPositionMouse.Y - locationMouse.Y)));
                OldPositionMouse = locationMouse;
                IsSave = false;
            }
            else
                if (MovingPhysicalObject != null && ChoosePhysicalObject != null)
                {
                    _oldPositionMovingGameObject = MovingPhysicalObject.GetPosition();
                    MovingPhysicalObject.SetPosition(locationMouse);
                    IsSave = false;
                }

        }

        public bool IsChangeInfo()
        {
            if (MovingPhysicalObject != null)
            {
                if (_oldPositionMovingGameObject.X != MovingPhysicalObject.GetPosition().X)
                    return true;
                if (_oldPositionMovingGameObject.Y != MovingPhysicalObject.GetPosition().Y)
                    return true;
            }
            return false;
        }


        public bool PlaceMovingGameObject()
        {
            if (MovingPhysicalObject == null) return false;
            if (!_makedPhysicalObjects.Contains(MovingPhysicalObject))
            {
                _makedPhysicalObjects.Add(MovingPhysicalObject);
                MovingPhysicalObject.SetPosition(
                    new Point(MovingPhysicalObject.GetPosition().X - Center.X,
                        MovingPhysicalObject.GetPosition().Y - Center.Y));

            }
            LastMovingGameObject = MovingPhysicalObject;
            MovingPhysicalObject = null;
            return true;
        }

        public bool CancelChoose()
        {
            if (MovingPhysicalObject != null)
            {
                _makedPhysicalObjects.Remove(MovingPhysicalObject);
                LastMovingGameObject = MovingPhysicalObject = null;
                if (_makedPhysicalObjects.Count > 0)
                {
                    LastMovingGameObject = _makedPhysicalObjects.Last();
                }
                return true;
            }
            return false;
        }

        public void DeleteObject()
        {
            _makedPhysicalObjects.Remove(LastMovingGameObject);
        }

        public void MarkGameObject(Point positionClick)
        {
            if (ShowAllObjects)
            {
                int index = _frame.ClickOnFrame(positionClick);
                if (index != -1 && index < _accessPhysicalObjects.Count)
                {
                    CurrentPhysicalObject = _accessPhysicalObjects[index];
                }
            }
        }

        public void CheckClick(Point locationClick)
        {

            OldPositionMouse = locationClick;
            if (MovingPhysicalObject == null)
            {

                Cursor.Current = Cursors.Hand;
                OldPositionMouse = locationClick;


                foreach (var makedPhysicalObject in _makedPhysicalObjects)
                {
                    if (Center.X + makedPhysicalObject.GetPosition().X <= locationClick.X &&
                        locationClick.X <=
                        Center.X + makedPhysicalObject.GetPosition().X +
                        makedPhysicalObject.GetDimension().Width)
                        if (Center.Y + makedPhysicalObject.GetPosition().Y <= locationClick.Y &&
                            locationClick.Y <=
                            Center.Y + makedPhysicalObject.GetPosition().Y +
                            makedPhysicalObject.GetDimension().Height)
                        {
                            LastMovingGameObject = MovingPhysicalObject = makedPhysicalObject;
                            ChoosePhysicalObject = null;
                        }
                }
            }
        }

        public void HighLightLastMovingGameObject(Graphics device)
        {
            if (LastMovingGameObject != null)
            {
                //if (LastMovingGameObject == MovingPhysicalObject)
                //    device.DrawRectangle(Pens.Red, LastMovingGameObject.Position.X, LastMovingGameObject.Position.Y,
                //        LastMovingGameObject.size.Width, LastMovingGameObject.size.Height);
                //else
                //{
                //    device.DrawRectangle(Pens.Red, axis.Center.X + LastMovingGameObject.Position.X, axis.Center.Y + LastMovingGameObject.Position.Y,
                //        LastMovingGameObject.size.Width, LastMovingGameObject.size.Height);
                //}
            }
        }

        public List<PhysObject.PhysObject> GetMakedObjects()
        {
            return _makedPhysicalObjects;
        }

        public void Draw(Graphics device, Button buttonChoose)
        {
            if (!IsOn) return;
            ShowMovingGameObject(device);
            ShowMakedGameObjects(device);
            if (ShowAllObjects)
            {
                _frame.PaintFrame(device);
                ShowScrollAccessGameObjects(device, buttonChoose);
            }
        }

        public void SaveClick(MouseEventArgs e)
        {
            OldPositionMouse = e.Location;
            if (MovingPhysicalObject == null)
                CheckClick(e.Location);

            Cursor.Current = Cursors.Hand;
            IsClick = true;
        }

        public void CancelClick()
        {
            Cursor.Current = Cursors.Arrow;
            IsClick = false;
        }

        public void ReactionClick(MouseEventArgs arg)
        {
            MarkGameObject(arg.Location);

            if (arg.Button == MouseButtons.Right && CancelChoose())
            {
                return;
            }
            PlaceMovingGameObject();
        }

        public void SetInfoObject(TextBox textBoxName, TextBox textBoxPositionX, TextBox textBoxPositionY,
            TextBox textBoxSizeWidth, TextBox textBoxSizeHeight)
        {
            if (LastMovingGameObject != null)
            {
                LastMovingGameObject.SetName(textBoxName.Text);
                if (LastMovingGameObject.GetPosition().X != int.Parse(textBoxPositionX.Text) || LastMovingGameObject.GetPosition().Y != int.Parse(textBoxPositionY.Text))
                    IsSave = false;
                LastMovingGameObject.SetPosition(new Point(int.Parse(textBoxPositionX.Text), int.Parse(textBoxPositionY.Text)));
                LastMovingGameObject.SetDimension(new Size(int.Parse(textBoxSizeWidth.Text), int.Parse(textBoxSizeHeight.Text)));
            }
        }

        public void ShowInfo(TextBox textBoxName, TextBox textBoxPositionX, TextBox textBoxPositionY,
            TextBox textBoxSizeWidth, TextBox textBoxSizeHeight, TextBox textBoxNameTexture)
        {
            if (!IsChangeInfo()) return;
            textBoxName.Text = LastMovingGameObject.GetObjectName();
            textBoxPositionX.Text = LastMovingGameObject.GetPosition().X.ToString();
            textBoxPositionY.Text = LastMovingGameObject.GetPosition().Y.ToString();
            textBoxSizeWidth.Text = LastMovingGameObject.GetDimension().Width.ToString();
            textBoxSizeHeight.Text = LastMovingGameObject.GetDimension().Height.ToString();
            textBoxNameTexture.Text = (string)LastMovingGameObject.GetTexture().Tag;
        }

        public bool LastObjectIsNotNull()
        {
            return (LastMovingGameObject != null && IsOn);
        }

        private void Move(Point mouseLocation)
        {
            int positionX = -(OldPositionMouse.X - mouseLocation.X);
            int positionY = -(OldPositionMouse.Y - mouseLocation.Y);
            Center = new Point(Center.X + positionX, Center.Y + positionY);
            OldPositionMouse.X = mouseLocation.X;
            OldPositionMouse.Y = mouseLocation.Y;
        }

        public void CheckMouseMove(Point locationMouse)
        {
            if (IsClick && MovingPhysicalObject == null)
                Move(locationMouse);
            else
                MoveChooseGameObject(locationMouse);
        }

        public void Save()
        {
            SaveFileDialog saveFileDialog1 =
                new SaveFileDialog { Filter = "txt files (*.txt)|*.txt|все файлы(*.*)|*.*" };
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                SaveAs(saveFileDialog1.FileName);
            }
        }

        public void Open()
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                OpenFile(openFileDialog.FileName);
            }
        }

        public void SetTextureLastGameObject()
        {
            if (LastMovingGameObject != null)
            {
                OpenFileDialog openFileDialog = new OpenFileDialog();
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    LastMovingGameObject.SetTexture(FileMapManager.LoadTexture(openFileDialog.FileName));
                }

            }
        }

        public List<PhysObject.PhysObject> GetMakedPhysObjects()
        {
            return _makedPhysicalObjects;
        }

    }
}
